from django.db import models
from django.utils.translation import ugettext_lazy as _
import settings
import os
from django.core.serializers.json import DjangoJSONEncoder
import json
import datetime

class ATTRIBUTE_TYPES():
    TEXT = 0
    DATE = 1
    INTEGER = 2
    DECIMAL = 3
    CHOICE = 4
    
    tuple = ((0, _('Text')),
            (1, _('Date')),
            (2, _('Integer')),
            (3, _('Decimal')),
            (4, _('Choice'))
            )

class User(models.Model):
    class Meta:
        db_table = 'user'
        ordering = ['last_name', 'first_name']
    
    first_name = models.CharField(_('First name'), max_length=100)
    last_name = models.CharField(_('Last name'), max_length=100)
    login = models.CharField(_('Login'), max_length=30, unique=True)
    password = models.CharField(max_length=100)
    email = models.EmailField(_('E-mail'), max_length=100, unique=True)
    
    def __unicode__(self):
        return "%s %s"%(self.first_name, self.last_name)
    
    def check_password(self, password):
        return self.password == password

class Profile(models.Model):
    class Meta:
        db_table = 'profile'
        ordering = ['name']
    
    name = models.CharField(_('Name'), max_length=100)
    user = models.ForeignKey(User)
    
    def __unicode__(self):
        return self.name
    
    def profile_attributes(self):
        return self.profileattribute_set.order_by('name')
    
    @property
    def last_update(self):
        return self.file_set.aggregate(models.Max('created'))
    
    def to_json(self):
#        d={'id': self.id, 'name': self.name, 'last_update': self.last_update, 'attributes': [a.to_json() for a in self.profile_attributes()]}
        d={'id': self.id, 'name': self.name, 'attributes': [a.to_json() for a in self.profile_attributes()]}
        return d
        
class ProfileAttribute(models.Model):
    class Meta:
        db_table = 'profile_attribute'
        unique_together = ('name','profile')
        ordering = ['name']
    
    name = models.CharField(_('Name'), max_length=100)
    type = models.IntegerField(_('Type'), choices=ATTRIBUTE_TYPES.tuple, default=0)
    mandatory = models.BooleanField(_('Mandatory'))
    default_value = models.CharField(_('Default value'), max_length=200, null=True, blank=True)
    profile = models.ForeignKey(Profile, verbose_name=_('Profile'))
    
    decimal_places = models.IntegerField(null=True)
    
    def to_json(self):
        return {'id': self.id, 'name': self.name, 'type': self.type, 'mandatory': self.mandatory, 'default_value': self.default_value}
    
class ProfileAttributeChoice(models.Model):
    class Meta:
        db_table = 'profile_attribute_choice'
        unique_together = ('name','profile_attribute')
        ordering = ['name']
    
    name = models.CharField(_('Name'), max_length=100)
    profile_attribute = models.ForeignKey(ProfileAttribute)
    
class File(models.Model):
    class Meta:
        db_table = 'file'
        ordering = ['-created']
    
    created = models.DateTimeField(_('Uploaded'), auto_now_add=True)
    user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    profile = models.ForeignKey(Profile)
    name = models.CharField(_('Name'), max_length=260)
    size = models.BigIntegerField(_('Size'), default=0)
    version = models.IntegerField(_('Version'), default=1)
    parent = models.ForeignKey('self', null=True)
    active = models.BooleanField(default=True)
    
    @property
    def path(self):
        return os.path.join(settings.STORAGE, self.profile.name, self.name)
    
    def to_json(self):
        #dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None
        #d={'name': self.name, 'created': json.dumps(self.created.isoformat().)}
        d={'id': self.id, 'name': self.name, 'created': self.created.strftime('%Y-%m-%d %H:%M:%S'),
           'attributes': [a.to_json() for a in self.attribute_set.all()]}

        return d
    
 
class Attribute(models.Model):
    class Meta:
        db_table = 'attribute'
        
    file = models.ForeignKey(File, null=True)
    profile_attribute = models.ForeignKey(ProfileAttribute)
    
    def value(self):
        if hasattr(self, 'dateattribute'):
            return self.dateattribute.value
        elif hasattr(self, 'integerattribute'):
            return self.integerattribute.value
        elif hasattr(self, 'textattribute'):
            return self.textattribute.value
        elif hasattr(self, 'decimalattribute'):
            if self.decimalattribute.value:
                f='%.'+'%d' %(self.profile_attribute.decimal_places or 1) + 'f'
                return f % self.decimalattribute.value
            return None
        elif hasattr(self, 'choiceattribute'):
            return self.profile_attribute.choice_name(self.choiceattribute.value)
    
    def true_attribute(self):
        if hasattr(self, 'dateattribute'):
            return self.dateattribute
        elif hasattr(self, 'integerattribute'):
            return self.integerattribute
        elif hasattr(self, 'textattribute'):
            return self.textattribute
        elif hasattr(self, 'decimalattribute'):
            return self.decimalattribute
        elif hasattr(self, 'choiceattribute'):
            return self.choiceattribute
    
    def type(self):
        if hasattr(self, 'dateattribute'):
            return ATTRIBUTE_TYPES.DATE
        elif hasattr(self, 'integerattribute'):
            return ATTRIBUTE_TYPES.INTEGER
        elif hasattr(self, 'textattribute'):
            return ATTRIBUTE_TYPES.TEXT
        elif hasattr(self, 'decimalattribute'):
            return ATTRIBUTE_TYPES.DECIMAL
        elif hasattr(self, 'choiceattribute'):
            return ATTRIBUTE_TYPES.CHOICE
        
    def to_json(self):
        return {'name': self.profile_attribute.name, 'value': self.value}
        
class TextAttribute(Attribute):
    class Meta:
        db_table = 'text_attribute'
    
    value = models.CharField(_('Text'), max_length=200, null=True, blank=True)
    
    def __unicode__(self):
        return self.value
    
class DateAttribute(Attribute):
    class Meta:
        db_table = 'date_attribute'
    
    value = models.DateField(_('Date'), null=True)
    
    def __unicode__(self):
        return unicode(self.value)
    
class IntegerAttribute(Attribute):
    class Meta:
        db_table = 'integer_attribute'
    
    value = models.BigIntegerField(_('Integer'), null=True)
    
    def __unicode__(self):
        return unicode(self.value)
        
class DecimalAttribute(Attribute):
    class Meta:
        db_table = 'decimal_attribute'
    
    value = models.FloatField(_('Decimal'), null=True)
    
    def __unicode__(self):
        return unicode(self.value)
    
class ChoiceAttribute(Attribute):
    class Meta:
        db_table = 'choice_attribute'
    
    value = models.CharField(_('Choice'), max_length=10, null=True)
    
    def __unicode__(self):
        return unicode(self.value)
